#pragma once
#include <iostream>
#include "Thread.hpp"
#include "Lock.hpp"
#include "log.hpp"
#include "cond.hpp"
#include <vector>
#include <queue>
const int defaultnum = 5;
using namespace LogModule;
template <class T>
class ThreadPool
{
public:
    ThreadPool(int num = defaultnum)
        : _tnum(num), isrunning(false), sleepnum(0)
    {
        for (int i = 0; i < _tnum; i++)
        {
            _threads.emplace_back(
                [this]()
                {
                    Handatask();
                })
        }
    }
    void Start()
    {
        if (isrunning)
        {
            return;
        }
        isrunning = true;
        for (auto &thread : _threads)
        {
            thread.Start();
            LOG(LogLevel::INFO) << "start new thread" << thread.Getname();
        }
    }
    void Stop()
    {
        if(!isrunning)
        {
            LOG(LogLevel::WARNING)<<"线程池已经停止";
            return;
        }
        isrunning=false;
        //唤醒所有线程，并退出
        Wakeup_wall();
    }
    void Wakeup_one()
    {
        // 唤醒一个线程
        if (isrunning)
        {
            _cond.Notify();
        }
    }
    void Wakeup_wall()
    {
        // 唤醒所有线程
        if (isrunning)
        {
            _cond.Notifyall();
        }
    }
    // 线程元素的回调函数：从任务队列中获得任务并执行
    void Handatask()
    {
        while (1)
        {
            T a;
            LockGuard lock(_mutex);
            while (_taskq.empty() && isrunning)
            {
                sleepnum++;
                // 在条件变量下等待并释放锁
                _cond.Wait(_mutex);
                sleepnum--;
            }
            if(_taskq.empty&&isrunning==false)
            {
                //说明任务队列为空，线程池要停止：
                LOG(LockLevel::INFO)<<"任务队列为空，线程池退出！";
                break;
            }
            // 有两种情况
            //1.线程池已经标记为停止状态，但还需要处理完任务队列中的任务
            //2.线程池正常运行处理任务
            a = _taskq.front();
            _taskq.pop();
            a();
        }
    }
    ~ThreadPool()
    {
    }
    //线程池统一回收：
    bool Join()
    {
        if(!isrunning)
        {
            for(auto& thread:_threads)
            {
                thread.join();
            }
            return true;
        }
        return false;
    }
    void Enquenue(T &task)
    {
        if (isrunning)
        {
            LockGuard lock(_mutex);
            _taskq.push(task);
            // 当所有线程都在阻塞时唤醒一个线程来执行任务
            if (_threads.size() == sleepnum)
            {
                Wakeup_one();
            }
        }
    }

private:
    std::vector<Thread> _threads;
    // 线程池中线程的个数
    int _tnum;
    std::queue<T> _taskq;

    Mutex _mutex;
    Cond _cond;

    bool isrunning;
    int sleepnum;
};